package pl.smath.renderer.model;

import com.google.gwt.user.client.ui.RootPanel;

import gwt.g2d.client.graphics.Surface;
import pl.smath.expression.model.presentation.IntervalClosureType;
import pl.smath.renderer.renderer.TermRendererException;
import pl.smath.renderer.utils.Cursor;
import pl.smath.renderer.utils.InteractionSocket;
import pl.smath.renderer.utils.Rectangle;

public class IntervalView extends View {

	private View first;
	private View second;
	private Double space;
	private IntervalClosureType closureType;
	
	public IntervalView(IntervalClosureType closureType, View first, View second) {
		super("(,)");
		setFirst(first);
		setSecond(second);
		this.closureType = closureType;
		this.space = 0d;
	}

	/**
	 * @return the first
	 */
	public View getFirst() {
		return first;
	}

	/**
	 * @param first the first to set
	 */
	public void setFirst(View first) {
		this.first = first;
	}

	/**
	 * @return the second
	 */
	public View getSecond() {
		return second;
	}

	/**
	 * @param second the second to set
	 */
	public void setSecond(View second) {
		this.second = second;
	}

	/**
	 * render text at the current position
	 * @param canvas
	 */
	@Override
	public void render(Surface canvas, InteractionSocket socket) throws TermRendererException {
		//TODO brackets
		Surface surface = new Surface();
		surface.setFont(this.getFont());
		Cursor cursor = this.getCursor();
		Double leftOpenBracketWidth = canvas.measureText("(");
		Double leftClosedBracketWidth = canvas.measureText("<");
		Double commaWidth = canvas.measureText(",");
		
		if ((this.getFont() == null)||(this.getFontHeight() == null)) {
			this.setFont(canvas.getFont());
		}
		canvas.setFont(this.getFont());
		
		if (isNegative()) {
			this.minusSign.render(canvas, new Cursor(cursor.getX(), this.getCursor().getY() - this.getBaselineOffset()));
		}
		
		if (closureType == IntervalClosureType.OPEN  ||  closureType == IntervalClosureType.OPEN_CLOSED) {
			canvas.fillText("(", cursor.getX(), cursor.getY());
			cursor.setX(cursor.getX() + leftOpenBracketWidth + space);
		} else {
			canvas.fillText("<", cursor.getX(), cursor.getY());
			cursor.setX(cursor.getX() + leftClosedBracketWidth + space);
		}
		
		this.first.render(canvas, socket);
		canvas.fillText(",", cursor.getX() + first.getWidth(), cursor.getY());
		this.second.render(canvas, socket);
		cursor.setX(cursor.getX() + first.getWidth() + commaWidth  + space*2 + second.getWidth());
		
		if (closureType == IntervalClosureType.OPEN  ||  closureType == IntervalClosureType.CLOSED_OPEN){
			canvas.fillText(")", cursor.getX(), cursor.getY());
		} else {
			canvas.fillText(">", cursor.getX(), cursor.getY());
		}
		
	}

	/**
	 * set the position on canvas to render
	 * @param Cursor
	 */
	@Override
	public void setCursor(Cursor cursor) {
		cursor.setY(cursor.getY());
		
		Surface surface = new Surface();
		RootPanel.get().add(surface);
		surface.setFont(this.getFont());

		Double leftOpenBracketWidth = surface.measureText("(");
		Double rightOpenBracketWidth = surface.measureText(")");
		Double leftClosedBracketWidth = surface.measureText("<");
		Double rightClosedBracketWidth = surface.measureText(">");
		Double commaWidth = surface.measureText(",");
		
		surface.setFont(this.font);
		Double minusWidth = 0d;
		if (this.isNegative()) minusWidth = this.minusSign.getWidth();
		
		
		super.setCursor(new Cursor(cursor.getX(), cursor.getY()));
		
		if (this.isNegative()) {
			cursor.setX(cursor.getX() + minusWidth);
		}

		Cursor toSet = new Cursor(cursor.getX(), cursor.getY());
		
		if (closureType == IntervalClosureType.OPEN  ||  closureType == IntervalClosureType.OPEN_CLOSED)
			toSet.setX(toSet.getX() + leftOpenBracketWidth + space);
		else
			toSet.setX(toSet.getX() + leftClosedBracketWidth + space);
		
		first.setCursor(new Cursor(toSet.getX(), toSet.getY()));
		
		toSet.setX(toSet.getX() + first.getWidth() + commaWidth + space);
			
		second.setCursor(new Cursor(toSet.getX(), toSet.getY()));

		if (closureType == IntervalClosureType.OPEN  ||  closureType == IntervalClosureType.CLOSED_OPEN)
			toSet.setX(toSet.getX() + rightOpenBracketWidth + space);
		else
			toSet.setX(toSet.getX() + rightClosedBracketWidth + space);

		RootPanel.get().remove(surface);
	}
	
	/**
	 * @param font the font to set
	 */
	@Override
	public void setFont(String font) {
		this.first.setFont(font);
		this.second.setFont(font);

		if (font.indexOf("px")!=-1) {
			this.setFontHeight(new Double(font.substring(0, font.indexOf("px"))));
			this.font = font.substring(font.indexOf("px ")+3);
			this.minusSign.setFont(this.font, this.getFontHeight());
			space = getFontHeight()*0.07d;			
			update();
		} else {
			this.setFontHeight(null);
			this.font = null;
		}

	}
	
	/**
	 * updates the view after changes
	 */
	@Override
	public void update() {
		Surface surface = new Surface();
		RootPanel.get().add(surface);
		surface.setFont(this.getFont());

		Double leftOpenBracketWidth = surface.measureText("(");
		Double rightOpenBracketWidth = surface.measureText(")");
		Double leftClosedBracketWidth = surface.measureText("<");
		Double rightClosedBracketWidth = surface.measureText(">");
		Double commaWidth = surface.measureText(",");
		
		surface.setFont(this.getFont());
		
		Double minusWidth = 0d;
		
		if (isNegative()) 
			minusWidth = this.minusSign.getWidth();

		Double artifactsWidth = 0.0d;

		if (closureType == IntervalClosureType.OPEN  ||  closureType == IntervalClosureType.OPEN_CLOSED)
			artifactsWidth += leftOpenBracketWidth;
		else
			artifactsWidth += leftClosedBracketWidth;

		artifactsWidth += commaWidth;
		
		if (closureType == IntervalClosureType.OPEN  ||  closureType == IntervalClosureType.CLOSED_OPEN)
			artifactsWidth += rightOpenBracketWidth;
		else
			artifactsWidth += rightClosedBracketWidth;
		
		artifactsWidth += space*3;
		
		this.setWidth(first.getWidth() + second.getWidth() + artifactsWidth);
		this.setHeight(Math.max(first.getHeight(), second.getHeight()));


		RootPanel.get().remove(surface);
	}
	
}
